package com.wmh.baseservice.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.wmh.baseservice.common.ex.ServiceException;
import com.wmh.baseservice.common.mybatisplus.methods.CommonServiceImpl;
import com.wmh.baseservice.common.redis.config.RedisConfig;
import com.wmh.baseservice.common.redis.utils.RedisUtil;
import com.wmh.baseservice.common.shiro.config.ShiroConfig;
import com.wmh.baseservice.common.shiro.jwt.JwtTokenUtil;
import com.wmh.baseservice.common.utils.CommUtil;
import com.wmh.baseservice.common.utils.LogUtil;
import com.wmh.baseservice.common.utils.PathUtil;
import com.wmh.baseservice.common.utils.ShiroMd5Util;
import com.wmh.baseservice.common.utils.upload.service.CosService;
import com.wmh.baseservice.user.mapper.UsInfoMapper;
import com.wmh.baseservice.user.pojo.UsInfo;
import com.wmh.baseservice.user.pojo.UsRolePermissions;
import com.wmh.baseservice.user.pojo.vo.UsInfoRespVO;
import com.wmh.baseservice.user.service.UsInfoService;
import com.wmh.baseservice.user.service.UsRolePermissionsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.rmi.ServerException;
import java.util.*;

/**
 * @author mmx generator
 * @since 2021-07-23
 */
@Service
@Slf4j
public class UsInfoServiceImpl extends CommonServiceImpl<UsInfoMapper, UsInfo> implements UsInfoService {

    @Resource
    private UsInfoMapper usInfoMapper;
    @Resource
    private UsRolePermissionsService usRolePermissionsService;
    @Resource
    private RedisUtil redisUtil;

    @Resource
    private CosService cosService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject login(String openid, Long parentId) {
        JSONObject jsonObject = new JSONObject(true);
        UsInfo usInfo = super.getOneForUpdate(new QueryWrapper<UsInfo>().eq(UsInfo.OPEN_ID, openid));
        if (!CommUtil.checkNull(usInfo)) {
            //生成随机邀请码
            //新用户
            String salt = ShiroMd5Util.createSalt();
            usInfo = new UsInfo().setOpenId(openid).setSalt(salt).setPassword("sso").setLoginCount(1).setLoginTime(new Date()).setStatus(0).setInviteId(-1L);
            //添加用户默认角色
            if (!super.save(usInfo)) {
                throw new ServiceException();
            }
            jsonObject.put("newUser", 1);
            UsRolePermissions usRolePermissions = new UsRolePermissions().setRole("user").setUsId(usInfo.getId()).setType(1);
            if (!usRolePermissionsService.save(usRolePermissions)) {
                throw new ServiceException();
            }
            //添加到redis队列中
            String project = RedisConfig.KEY_INFO;
            String key = "role_permissions_" + usInfo.getId() + ShiroConfig.SHIRO_USER + project;
            try {
                SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
                Set<String> roles = new HashSet<>();
                roles.add(usRolePermissions.getRole());
                info.setRoles(roles);
                info.setStringPermissions(null);
                redisUtil.set(key, info);
            } catch (Exception e) {
                LogUtil.error("redis角色权限添加错误,key是:" + key + "。原因是:" + e.getMessage());
            }
        } else {
            //旧用户
            usInfo.setLoginCount(usInfo.getLoginCount() + 1);
            usInfo.setLoginTime(new Date());
            if (usInfoMapper.updateById(usInfo) != 1) {
                throw new ServiceException();
            }
        }
        if (!CommUtil.checkNull(usInfo)) {
            throw new ServiceException("用户不存在");
        }
        //分享进来的绑定父id,终身只绑定一次
        if (CommUtil.checkNull(parentId)) {
            UsInfo parentInfo = getByIdForUpdate(parentId);
            if (CommUtil.checkNull(parentInfo)  && !parentId.equals(usInfo.getId())) {
                usInfo.setInviteId(parentId);
                if (!updateById(usInfo)) {
                    throw new ServiceException("绑定邀请人失败");
                }
            }
        }
        //返回推荐人信息
        if (CommUtil.checkNull(usInfo) && usInfo.getInviteId() != -1) {
            UsInfo parent = getByIdForUpdate(usInfo.getInviteId());
            if (CommUtil.checkNull(parent)) {
                jsonObject.put("parentNick", parent.getNick());
                jsonObject.put("parentAvatar", parent.getAvatar());
            }
        }
        // 秘钥
        jsonObject.put("token", "Bearer_" + JwtTokenUtil.generateToken(usInfo.getId(), usInfo.getOpenId() + ShiroConfig.SHIRO_SSO + ":" + "sso", 60000000));
        return jsonObject;
    }

    @Override
    public  List<Long> promoteCommission(Long id) {
        return usInfoMapper.promoteCommission(id);
    }

    @Override
    public UsInfoRespVO getAvatarAndNickByUsId(Long usId) {
        return usInfoMapper.getAvatarAndNickByUsId(usId);
    }

    @Override
    public void editUsInfo(String nick, MultipartFile avatar, String phone, Long usId) throws IOException {

        UpdateWrapper<UsInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", usId);

        boolean updateRequired = false;

        if (StringUtils.isNotBlank(nick)) {
            updateWrapper.set("nick", nick);
            updateRequired = true;
        }
        if (avatar != null && !avatar.isEmpty()) {
            // 生成头像唯一文件名
            String avatarUniqueFileName = CommUtil.generateUniqueFileName(Objects.requireNonNull(avatar.getOriginalFilename()));
            String suffix = avatarUniqueFileName.substring(avatarUniqueFileName.lastIndexOf("."));
            // 判断文件格式是否支持
            if (!".jpg,.jpeg,.png,.gif".contains(suffix.trim().toLowerCase())) {
                throw new IllegalArgumentException("图片格式不支持");
            }
            // 上传图片并获取图片路径
            String upload = cosService.upload(avatar.getBytes(), "user_avatar/" + avatarUniqueFileName);
            String imgPath = PathUtil.COS_DOMAIN + upload;
            updateWrapper.set("avatar", imgPath);
            updateRequired = true;
        }
        if (StringUtils.isNotBlank(phone)) {
            updateWrapper.set("phone", phone);
            updateRequired = true;
        }

        if (updateRequired) {
            int rows = usInfoMapper.update(null, updateWrapper);
            if (rows == 0) {
                // 抛出异常
                throw new ServerException("更新失败, 请稍后重试");
            }
        }
    }

    /**
     * 检查用户是否为新用户（头像和昵称是否都为空）
     * @param userId 用户ID
     * @return 如果头像和昵称都为空，返回 false, 否则返回 true
     */
    @Override
    public Boolean isNewUser(Long userId) {
        UsInfo user = usInfoMapper.selectById(userId);
        if (user != null) {
            return !(StringUtils.isBlank(user.getAvatar()) && StringUtils.isBlank(user.getNick()));
        }
        return false; // 如果用户不存在返回 false
    }

    /**
     * 根据用户id设置头像url
     * @param usId 用户id
     * @param imgUrl 头像图片url
     */
    @Override
    public void setUserAvatar(Long usId, String imgUrl) {
        UsInfo usInfo = usInfoMapper.selectById(usId);
        usInfo.setAvatar(imgUrl);
        usInfoMapper.updateById(usInfo);
    }

    @Override
    public BigDecimal getBalanceById(Long usId) {
        return usInfoMapper.getBalanceById(usId);
    }
}
